#pragma once

#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/time.h>
#include <atomic>
#include <fstream>
#include <vector>
#include <boost/algorithm/string.hpp>

namespace ns_util
{

#define TEMP_PATH "./temp/"

  class TimeUtil
  {
  public:
    static std::string gettime()
    {
      struct timeval _time;
      gettimeofday(&_time, nullptr);
      return std::to_string(_time.tv_sec);
    }
    static std::string getMillTime()
    {
      struct timeval _time;
      gettimeofday(&_time, nullptr);
      return std::to_string(_time.tv_sec * 1000 + _time.tv_usec / 1000);
    }
  };
  class PathUtil
  {
  public:
    static std::string addsuffix(const std::string &filename, const std::string suffix)
    {
      std::string path = TEMP_PATH;
      path += filename;
      path += suffix;

      return path;
    }
    static std::string src(const std::string &filename, std::string language)
    {
      if (language == "cpp")
      {
        return addsuffix(filename, ".cpp");
      }
      else if (language == "python")
      {
        return addsuffix(filename, ".py");
      }
      else if (language == "go")
      {
        return addsuffix(filename, ".go");
      }
      else if (language == "c")
      {
        return addsuffix(filename, ".c");
      }
      else{
        exit(-1);
      }
    }
    static std::string exe(const std::string &filename)
    {

      return addsuffix(filename, ".exe");
    }
    static std::string compileError(const std::string &filename)
    {
      return addsuffix(filename, ".compile_error");
    }
    // 运行类的

    static std::string stdcin(const std::string &filename)
    {
      return addsuffix(filename, ".stdcin");
    }
    static std::string stdcout(const std::string &filename)
    {
      return addsuffix(filename, ".stdcout");
    }
    static std::string stderror(const std::string &filename)
    {
      return addsuffix(filename, ".stderror");
    }
  };

  class FileUtil
  {
  public:
    static bool isFileExist(const std::string &path)
    {
      struct stat _stat;
      if (stat(path.c_str(), &_stat) == 0)
      {
        return true;
      }
      return false;
    }
    // 唯一文件名
    static std::string UniqueName()
    {
      static std::atomic_int id(1);
      std::string ret;
      ret += TimeUtil::getMillTime();
      ret += "_";
      ret += std::to_string(id);
      ++id;
      return ret;
    }
    // 代码写入文件
    static bool WriteFile(const std::string &target /*文件名*/, const std::string &source /*存的是代码*/)
    {
      std::ofstream out(target);
      if (!out.is_open())
        return false;

      out.write(source.c_str(), source.size());
      out.close();
      return true;
    }
    // 从文件中读取运行或者编译的结果
    static bool ReadFile(const std::string &target /*文件名*/, std::string *source, bool keep = false)
    {
      std::ifstream in(target);
      if (!in.is_open())
        return false;

      std::string line;
      while (std::getline(in, line))
      {
        (*source) += line;
        (*source) += (keep ? "\n" : "");
      }
      in.close();
      return true;
    }
  };
  class FileSplit
  {
  public:
    static void SplitString(const std::string &str, std::vector<std::string> *target, const std::string &spl)
    {
      boost::split((*target), str, boost::is_any_of(spl), boost::algorithm::token_compress_on);
    }
  };
}
